﻿using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace Najak
{
	public partial class InputHandler
	{
		private List<KeyPressEvent> RegisteredKeys = new List<KeyPressEvent>();
		private List<MouseEvent> RegisteredMouseEvents = new List<MouseEvent>();

		private Dictionary<object, List<Action<Keys>>> RegisteredKeyListeners = new Dictionary<object, List<Action<Keys>>>();
		private Dictionary<object, List<Action<MouseEvent>>> RegisteredMouseListeners = new Dictionary<object, List<Action<MouseEvent>>>();

		public void RegisterForMouseEvent(object listener, MouseEventTypes types, MouseButtons buttons, KeyboardModes modes,  Action<MouseEvent> action)
		{
			foreach (MouseEvent e in RegisteredMouseEvents)
			{
				if (e.Types == types && e.Buttons == buttons && e.KeyboardMode == modes && e.Action == action)
					return;
			}
			MouseEvent evt = new MouseEvent();
			evt.Types = types;
			evt.Buttons = buttons;
			evt.KeyboardMode = modes;
			evt.Action = action;
			RegisteredMouseEvents.Add(evt);
			_OnMouseListenerRegistered(listener, action);
		}
		private void _OnMouseListenerRegistered(object listener, Action<MouseEvent> action)
		{
			List<Action<MouseEvent>> handlers;
			if (!RegisteredMouseListeners.TryGetValue(listener, out handlers))
			{
				handlers = new List<Action<MouseEvent>>();
				RegisteredMouseListeners.Add(listener, handlers);
			}
			handlers.Add(action);
		}


		public void UnregisterMouseEventHandler(object listener, Action<MouseEvent> action)
		{
			_UnregisterMouseEventHandler(action);

			List<Action<MouseEvent>> handlers;
			if (RegisteredMouseListeners.TryGetValue(listener, out handlers))
			{
				handlers.Remove(action);

				if (handlers.Count == 0)
					RegisteredMouseListeners.Remove(listener);
			}
		}

		private void _UnregisterMouseEventHandler(Action<MouseEvent> action)
		{
			for (int i = RegisteredMouseEvents.Count - 1; i >= 0; i--)
			{
				MouseEvent evt = RegisteredMouseEvents[i];
				if (evt.Action == action)
				{
					RegisteredMouseEvents.RemoveAt(i);
				}
			}
		}

		public void RegisterForKeyEvent(object listener, Keys key, Action<Keys> action, bool onlyOnce, bool requiresCtrl)
		{
			RegisterForKeyEvent(listener, key, action, onlyOnce, requiresCtrl, false);
		}

		public void RegisterForKeyEvent(object listener, Keys key, Action<Keys> action, bool onlyOnce, bool requiresCtrl, bool enableRepeat)
		{
			_OnKeyListenerRegistered(listener, action);
			_RegisterForKeyEvent(key, action, onlyOnce, requiresCtrl, enableRepeat);
		}

		public void RegisterForKeyEvent(object listener, Action<Keys> action, bool onlyOnce, bool requiresCtrl, params Keys[] keys)
		{
			_OnKeyListenerRegistered(listener, action);

			foreach (Keys k in keys)
			{
				_RegisterForKeyEvent(k, action, onlyOnce, requiresCtrl, false);
			}
		}


		private void _RegisterForKeyEvent(Keys key, Action<Keys> action, bool onlyOnce, bool requiresCtrl, bool enableRepeat)
		{
			foreach (KeyPressEvent e in RegisteredKeys)
			{
				if (e.Key == key && e.Action == action)
					return;
			}
			KeyPressEvent evt = new KeyPressEvent();
			evt.Key = key;
			evt.Action = action;
			evt.OnlyOnce = onlyOnce;
			evt.RequireCtrl = requiresCtrl;
			evt.EnableRepeat = enableRepeat;
			RegisteredKeys.Add(evt);

		}
		private void _OnKeyListenerRegistered(object listener, Action<Keys> action)
		{
			List<Action<Keys>> handlers;
			if (!RegisteredKeyListeners.TryGetValue(listener, out handlers))
			{
				handlers = new List<Action<Keys>>();
				RegisteredKeyListeners.Add(listener, handlers);
			}
			handlers.Add(action);
		}

		public void UnregisterKeyEventHandler(object listener, Action<Keys> action)
		{
			_UnregisterKeyEventHandler(action);
			List<Action<Keys>> handlers;
			if (RegisteredKeyListeners.TryGetValue(listener, out handlers))
			{
				handlers.Remove(action);

				if (handlers.Count == 0)
					RegisteredKeyListeners.Remove(listener);
			}
		}
		private void _UnregisterKeyEventHandler(Action<Keys> action)
		{
			for (int i = RegisteredKeys.Count - 1; i >= 0; i--)
			{
				KeyPressEvent evt = RegisteredKeys[i];
				if (evt.Action == action)
				{
					RegisteredKeys.RemoveAt(i);
				}
			}
		}

		public void NotifyListenerRemoved(object listener)
		{
			List<Action<Keys>> handlers;
			if (RegisteredKeyListeners.TryGetValue(listener, out handlers))
			{
				foreach (Action<Keys> h in handlers)
				{
					_UnregisterKeyEventHandler(h);
				}
				RegisteredKeyListeners.Remove(listener);
			}

			List<Action<MouseEvent>> mouseHandlers;
			if (RegisteredMouseListeners.TryGetValue(listener, out mouseHandlers))
			{
				foreach (Action<MouseEvent> mh in mouseHandlers)
				{
					_UnregisterMouseEventHandler(mh);
				}
				RegisteredMouseListeners.Remove(listener);
			}
		}


	}
}
